package com.zmj.sy.mom.srv.aps.feign;

import com.zmj.sy.mom.srv.aps.bean.dto.wms.PartsReportingAddDto;
import com.zmj.sy.mom.srv.aps.bean.dto.wms.WmsPartProcurementReqDto;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.Plate;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.PlatePhase;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.WmsPlatePick;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.LogApi;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestExcess;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestNest;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestPlate;
import com.zmj.sy.mom.srv.aps.bean.vo.part.PartInfoResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.workshop.WorkshopMatchEndReqVo;
import com.zmj.sy.mom.srv.aps.config.ProjectConfig;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.*;
import com.zmj.sy.mom.srv.aps.bean.entity.order.OrderBom;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsWorkDetail;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Component
public class WmsApiClient {

    private final RestTemplate restTemplate;
    ///wms
    private static final String WMS_URL = "http://erp-wms";
    private final PlatePhaseMapper platePhaseMapper;
    private final OrderBomMapper orderBomMapper;
    private final ApsWorkDetailMapper apsWorkDetailMapper;
    ExecutorService executor = Executors.newFixedThreadPool(30);
    private final LogApiUtils logApiUtils;
    private final SinoCamReceiveNestPlateMapper sinoCamReceiveNestPlateMapper;
    private final SinoCamReceiveNestNestMapper sinoCamReceiveNestNestMapper;
    private final SinoCamReceiveNestExcessMapper sinoCamReceiveNestExcessMapper;
    private final PlateMapper plateMapper;
    private final PartMapper partMapper;
    private final ApiLogUtils apiLogUtils;
    private final ProjectConfig projectConfig;

    /**
     * 领料通知WMS
     */
    public void sendLingliao(List<WmsPlatePick> pickList) {

        String url = WMS_URL + "/out/aps/apsMaterialPicking";
        LogApi logApi = logApiUtils.getSendLog("wms", "下发钢板领料单", url);

        Map<String, SinoCamReceiveNestPlate> sinoCamPlateMap = sinoCamReceiveNestPlateMapper.lambdaQuery()
                .in(SinoCamReceiveNestPlate::getStockListNo, pickList.stream().map(WmsPlatePick::getMaterialId).distinct().collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.toMap(SinoCamReceiveNestPlate::getStockListNo, Function.identity()));

        Map<Integer, SinoCamReceiveNestNest> nestMap = sinoCamReceiveNestNestMapper.lambdaQuery()
                .in(SinoCamReceiveNestNest::getReceiveNestId, sinoCamPlateMap.values().stream().map(SinoCamReceiveNestPlate::getReceiveNestId).distinct().collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.toMap(SinoCamReceiveNestNest::getReceiveNestId, Function.identity()));

        Map<String, Plate> plateMap = plateMapper.lambdaQuery()
                .in(Plate::getMaterCode, pickList.stream().map(WmsPlatePick::getMaterialId).distinct().collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.toMap(Plate::getMaterCode, Function.identity()));

        Map<Integer, List<SinoCamReceiveNestExcess>> excessMap = sinoCamReceiveNestExcessMapper.lambdaQuery()
                .in(SinoCamReceiveNestExcess::getReceiveNestId, sinoCamPlateMap.values().stream().map(SinoCamReceiveNestPlate::getReceiveNestId).distinct().collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.groupingBy(SinoCamReceiveNestExcess::getReceiveNestId));


        List<Map<String, Object>> req = new ArrayList<>();
        for (WmsPlatePick wmsPlatePick : pickList) {

            SinoCamReceiveNestPlate sinoPlate = sinoCamPlateMap.get(wmsPlatePick.getMaterialId());
            SinoCamReceiveNestNest sinoNest = nestMap.get(sinoPlate.getReceiveNestId());
            List<SinoCamReceiveNestExcess> sinoExcess = excessMap.get(sinoPlate.getReceiveNestId());
            Plate plate = plateMap.get(wmsPlatePick.getMaterialId());
            Map<String, Object> plateInfo = new HashMap<>();
            plateInfo.put("amount", sinoPlate.getAmount()); // 数量
            plateInfo.put("cloutWeight", sinoExcess == null ? new BigDecimal(0) : sinoExcess.stream().map(SinoCamReceiveNestExcess::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add)); // 余料重量
            plateInfo.put("length", sinoPlate.getLength()); // 长度
            plateInfo.put("width", sinoPlate.getWidth()); // 宽度
            plateInfo.put("plateThick", sinoPlate.getNorm()); // 钢板厚度
            plateInfo.put("materialCode", sinoPlate.getTexture()); // 钢板规格
            plateInfo.put("plateMaterial", sinoPlate.getTexture()); // 钢板材质
            plateInfo.put("materialId", wmsPlatePick.getMaterialId()); // 物料号
            plateInfo.put("nesting", sinoNest.getNestId()); // 套料图号
            PlatePhase phase = platePhaseMapper.lambdaQuery()
                    .eq(PlatePhase::getPlateCode, plate.getMaterCode())
                    .in(PlatePhase::getPhaseCode, "JG", "HG")
                    .one();
            plateInfo.put("nextWorkPlace", phase.getGroupCode()); // 下道工位


            plateInfo.put("nextWorkPlace", phase.getGroupCode()); // 下道工位
            plateInfo.put("planDate", sinoNest.getNeedDate()); // 计划日期
            plateInfo.put("plannedStartTime", sinoNest.getNeedDate()); // 计划开始时间
            plateInfo.put("plateState", 1); // 领料状态 1 待打包 2 待领用 3 已领用 4 已出库
            plateInfo.put("plateUsage", sinoNest.getRate()); // 钢板利用率
            plateInfo.put("type", 1); // 	钢板类型：1=钢板，2=余料，3=外委件
            plateInfo.put("wantDeliverDate", sinoNest.getNeedDate()); // 希望送货日期
            plateInfo.put("pickingListNo", wmsPlatePick.getPickingListNo());
            plateInfo.put("storagePlace", sinoPlate.getPositionCode());//堆垛位置
            plateInfo.put("sequence", sinoPlate.getSequence());//层号
            plateInfo.put("pickListItem", wmsPlatePick.getPickListItem());
            req.add(plateInfo);
        }


        String reqStr = JsonUtils.toJsonString(req);
        HttpHeaders headers = new HttpHeaders();
        headers.set("SOURCE", "APS");
        HttpEntity<List<Map<String, Object>>> entity = new HttpEntity<>(req, headers);
        try {
            logApiUtils.setReqStr(logApi, reqStr);
            String resStr = restTemplate.postForObject(url, entity, String.class);
            logApiUtils.successAndSave(logApi, resStr);
        } catch (Exception e) {
            String res = e.getMessage() != null && e.getMessage().length() > 500 ? e.getMessage().substring(0, 100) : e.getMessage();
            logApiUtils.errorAndSave(logApi, e.getMessage(), res);
        }

    }

    /**
     * 锁钢板
     *
     * @param nestAll
     * @param plateAll
     */
/*    public void sendTaoliao(List<SinoCamReceiveNestNest> nestAll, List<SinoCamReceiveNestPlate> plateAll) {
        Map<Integer, SinoCamReceiveNestNest> collect = nestAll.stream().collect(Collectors.toMap(SinoCamReceiveNestNest::getReceiveNestId, Function.identity()));

        List<Map<String, Object>> collect1 = plateAll.stream()
                .map(e -> {
                    SinoCamReceiveNestNest sinoCamReceiveNestNest = collect.get(e.getReceiveNestId());
                    Map<String, Object> map = new HashMap<>();
                    map.put("ncPath", null);//切割程序地址
                    map.put("nestingPath", sinoCamReceiveNestNest.getNestDxfUrl());//套料图地址
                    map.put("plateId", e.getStockListNo());
                    map.put("state", 1);
                    return map;
                })
                .collect(Collectors.toList());

        String url = "http://mom-app-wms/wms/nesting/info/plateNesting";
        log.info("WMS 发送请求地址：{} - 数据：{}", url, JsonUtils.toJsonString(collect1));
        String body = restTemplate.postForObject(url, collect1, String.class);
        log.info("WMS 发送响应地址：{} - 数据：{}", url, body);
    }*/

/*    public void zhuangpan(String palletCode, Integer partCount, String plmId, String uniqueSn, String phaseCode) {


        Map<String, Object> params = new HashMap<>();
        params.put("palletNumber", palletCode);
        params.put("requestState", 0);
        params.put("partCount", partCount);
        params.put("multipleType", 1);
        params.put("plmid", plmId);
        params.put("uniqueSn", uniqueSn);
        params.put("prevWorkPhase", phaseCode);

        String url = "http://mom-app-wms/wms/nesting/info/plateNesting";
        log.info("WMS 发送请求地址：{} - 数据：{}", url, JsonUtils.toJsonString(params));
        String body = restTemplate.postForObject(url, params, String.class);
        log.info("WMS 发送响应地址：{} - 数据：{}", url, body);

    }*/

    /**
     * 零件装盘
     */
    public void partPage(String palletCode) {
        String URL = WMS_URL + "/out/aps/reportWorkNew";
        LogApi logApi = logApiUtils.getSendLog("wms", "零件装盘", URL);
        List<PartInfoResVo> partInfos = partMapper.selectPartInfoResVo(palletCode).stream().filter(vo -> StringUtils.isNotBlank(vo.getPlmid())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(partInfos)) {
            return;
        }
            /*如果零件的下道工序是KJ，需检查零件的父级物料物料名称
        如果父物料名称中包含：耳板、内主筋、外主筋、过桥、固定脚踏板时，取其父级第一道工序、工作中心，作为零件的下道工序、下道工作组通知WMS
        如果父物料名称中不包含：耳板、内主筋、外主筋、过桥、固定脚踏板或为null时，通知WMS零件的下道工序为KJ，下道工作组为2-4_KJGW_00
        // nextNxphase=KJ*/
        for (PartInfoResVo vo : partInfos) {
            vo.setPartPath(String.format(projectConfig.getUrlPre(), vo.getPlmid(), vo.getPartPath()));
            if (WorkshopProp.KJ_PHASE_CODE.equals(vo.getNextNxphase())) {
                OrderBom orderBom = orderBomMapper.lambdaQuery().eq(OrderBom::getPlmId, vo.getPlmid()).last(" limit 1 ").one();
                if (orderBom != null) {
                    OrderBom orderBomP = orderBomMapper.lambdaQuery().eq(OrderBom::getId, orderBom.getPid()).last(" limit 1 ").one();
                    if (orderBomP != null && NameEqualsUtils.equals(orderBomP.getMaterName())) {
                        ApsWorkDetail apsWorkDetail = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getMaterNo, orderBomP.getPlmId()).orderByAsc(ApsWorkDetail::getPhaseSeq).last(" limit 1 ").one();
                        if (apsWorkDetail != null) {
                            vo.setNextNxphase(apsWorkDetail.getPhaseCode());
                            vo.setNextGroupNumber(apsWorkDetail.getGroupCode());
                        }

                    }
                }

            }

        }


        try {
            executor.execute(() -> {
                HttpHeaders header = new HttpHeaders();
                header.set("SOURCE", "APS");
                HttpEntity<Object> httpEntity = new HttpEntity<>(partInfos, header);
                logApiUtils.setReqStr(logApi, JsonUtils.toJsonString(partInfos));
                String post = restTemplate.postForObject(URL, httpEntity, String.class);
                logApiUtils.saveDB(true, logApi, post, 2);
                log.info("WMS-托盘同步-结束：" + post);
            });

        } catch (Exception e) {
            logApiUtils.saveDB(false, logApi, e.getMessage(), 2);
            log.info("WMS-报工并装盘-结束-错误：" + e.getMessage());
        }

    }

    /**
     * {
     * "endPalletNumber": "",
     * "startPalletNumber": ""
     * }
     */
    public void plateSyc(String palletCode) {
        String URL = WMS_URL + "/out/aps/reportWork";
        LogApi logApi = logApiUtils.getSendLog("wms", "托盘同步", URL);
        try {
            executor.execute(() -> {
                Map<String, Object> params = new HashMap<>();
                params.put("endPalletNumber", palletCode);
                String reqStr = JsonUtils.toJsonString(params);
                log.info("WMS-托盘同步-请求：" + JsonUtils.toJsonString(params));
                HttpHeaders header = new HttpHeaders();
                header.set("SOURCE", "APS");
                HttpEntity<Object> httpEntity = new HttpEntity<>(params, header);
                logApiUtils.setReqStr(logApi, reqStr);
                String post = restTemplate.postForObject(URL, httpEntity, String.class);
                logApiUtils.saveDB(true, logApi, post, 2);
                log.info("WMS-托盘同步-结束：" + post);
            });

        } catch (Exception e) {
            logApiUtils.saveDB(false, logApi, e.getMessage(), 2);
            log.info("WMS-报工并装盘-结束-错误：" + e.getMessage());
        }
    }

    public void AsseSyc(PartsReportingAddDto partReport) {
        String URL = WMS_URL + "/out/workReport/partsReporting";
        LogApi logApi = logApiUtils.getSendLog("wms", "通知wms报工", URL);
        List<PartsReportingAddDto> list = new LinkedList();
        list.add(partReport);
        try {
            executor.execute(() -> {
              /*  Map<String, List<PartsReportingAddDto>> params = new HashMap<>();
                params.put("partReport", list);*/
                log.info("组件到达-wms请求：" + JsonUtils.toJsonString(list));
                HttpHeaders header = new HttpHeaders();
                header.set("SOURCE", "APS");
                HttpEntity<Object> httpEntity = new HttpEntity<>(list, header);
                logApiUtils.setReqStr(logApi, JsonUtils.toJsonString(list));
/*
                SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
                requestFactory.setConnectTimeout(1000 * 60 * 10);
                requestFactory.setReadTimeout(1000 * 60 * 10);
                RestTemplate restTemplate2 = new RestTemplate(requestFactory);*/

                Map<String, Object> responseMap = restTemplate.postForObject(URL, httpEntity, Map.class);
                if (responseMap.get("code").equals(0) || responseMap.get("code").equals("0") || responseMap.get("code").equals(200) || responseMap.get("code").equals("200")) {
                    logApiUtils.saveDB(true, logApi, JsonUtils.toJsonString(responseMap), 2);
                } else {
                    logApiUtils.saveDB(false, logApi, (String) responseMap.get("message"), 2);
                }
            });

        } catch (Exception e) {
            logApiUtils.saveDB(false, logApi, e.getMessage(), 2);
            log.info("通知-错误：" + e.getMessage());
        }
    }

    /**
     * 拼点开工，清空工位上的托盘
     *
     * @param palletNumbers
     */
    public void clearPallet(List<String> palletNumbers) {
        String url = WMS_URL + "/out/aps/clearPallet";
        LogApi logApi = logApiUtils.getSendLog("wms", "清空托盘", url);
        try {
            List<Map<String, Object>> endPalletNumber = palletNumbers.stream().map(e -> {
                Map<String, Object> params = new HashMap<>();
                params.put("palletNumber", e);
                return params;
            }).collect(Collectors.toList());
            log.info("WMS-清空托盘-请求：" + JsonUtils.toJsonString(endPalletNumber));
            HttpHeaders header = new HttpHeaders();
            header.set("SOURCE", "APS");
            HttpEntity<Object> httpEntity = new HttpEntity<>(endPalletNumber, header);
            String reqStr = JsonUtils.toJsonString(httpEntity);
            logApiUtils.setReqStr(logApi, reqStr);
            String post = restTemplate.postForObject(url, httpEntity, String.class);
            logApiUtils.saveDB(true, logApi, post, 2);
            log.info("WMS-清空托盘-结束：" + post);
        } catch (Exception e) {
            logApiUtils.saveDB(false, logApi, e.getMessage(), 2);
            log.info("WMS-清空托盘结束-错误：" + e.getMessage());
        }
    }

    

/*    public void palletLeave(PositionTrayOutReqVo reqvo) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("trayId", reqvo.getTrayCode());
            params.put("palletType", reqvo.getTrayCode().substring(2, 4));
            params.put("asyMes", 0);
            params.put("agvFrom", reqvo.getPositionCode());
            params.put("accessSource", "aps");
            log.info("WMS-托盘同步-请求：" + JsonUtils.toJsonString(params));
            String post = restTemplate.postForObject("http://erp-wms/wms/out/agv/palletLeave", params, String.class);
            log.info("WMS-托盘同步-结束：" + post);
        } catch (Exception e) {
            log.info("WMS-报工并装盘-结束-错误：" + e.getMessage());
        }
    }*/

/*    public void trayIn(PositionTrayInReqVo reqVo) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("trayId", reqVo.getTrayCode());
            params.put("palletType", reqVo.getTrayCode().substring(2, 4));
            params.put("asyMes", 0);
            params.put("agvTo", reqVo.getPositionCode());
            params.put("accessSource", "aps");
            log.info("WMS-托盘同步-请求：" + JsonUtils.toJsonString(params));
            String post = restTemplate.postForObject("http://erp-wms/wms/out/agv/palletArive", params, String.class);
            log.info("WMS-托盘同步-结束：" + post);
        } catch (Exception e) {
            log.info("WMS-报工并装盘-结束-错误：" + e.getMessage());
        }
    }*/


/*    public void clearTuopan(List<String> tuopanList) {
        try {
            List<Map<String, Object>> params = new ArrayList<>();
            for (String tuopan : tuopanList) {
                Map<String, Object> map = new HashMap<>();
                map.put("palletNumber", tuopan);
                params.add(map);
            }
            log.info("WMS-托盘清空-请求：" + JsonUtils.toJsonString(params));
            String post = restTemplate.postForObject("http://erp-wms/wms/out/aps/clearPallet", params, String.class);
            log.info("WMS-托盘清空-结束：" + post);
        } catch (Exception e) {
            log.info("WMS-报工并装盘-结束-错误：" + e.getMessage());
        }

    }*/


    public void partProcurement(List<WmsPartProcurementReqDto> wmsReqDto, Integer id) {
        String url = "/sional/wgMaterialPick";
        LogApi logApi = logApiUtils.getSendLog("mom-srv-sf-pda", "下发外购件领料单", url);
        logApiUtils.setReq(logApi, wmsReqDto);
        logApi.setQueryParam(id.toString());
        log.info("WMS-外购件领料单-请求：" + JsonUtils.toJsonString(wmsReqDto));


        try {
            Map<String, Object> responseMap = restTemplate.postForObject("http://mom-srv-sf-pda" + url, wmsReqDto, Map.class);
            log.info("WMS-外购件领料单-响应：" + JsonUtils.toJsonString(responseMap));

            if (responseMap.get("code").equals(0) || responseMap.get("code").equals("0") || responseMap.get("code").equals(200) || responseMap.get("code").equals("200")) {
                logApiUtils.successAndSave(logApi, responseMap);
            } else {
                logApiUtils.errorAndSave(logApi, responseMap, (String) responseMap.get("message"));
            }
        } catch (Exception e) {
            logApiUtils.errorAndSave(logApi, "", e.getMessage());
            log.info("WMS-外购件领料单-错误{}：{}", id, e.getMessage());
//            logApiUtils.errorAndSave(logApi, null, e.getMessage());
//            throw SyExceptionUtils.e(e);
        }
    }

    /**
     * @Description: 配盘报工通知wms
     *
     * @author: hejiahui
     * @since: 2025/6/18 9:52
     */
    public void ppPartPage(WorkshopMatchEndReqVo reqVo) {
        if (ObjectUtils.isEmpty(reqVo)) {
            return;
        }
        String URL = WMS_URL + "/out/aps/reportWorkNew";
        LogApi logApi = logApiUtils.getSendLog("wms", "配盘报工", URL);
        List<PartInfoResVo> partInfos = new ArrayList<>();
        PartInfoResVo partInfoResVo = new PartInfoResVo();
        partInfoResVo.setPlmid(reqVo.getMatchcNo());
        partInfoResVo.setPalletCode(reqVo.getPalletNumber());
        partInfoResVo.setCuconstructNo(reqVo.getConstrNumber());
        partInfoResVo.setNxphase("PP");
        partInfoResVo.setNextNxphase("PZ");
        partInfoResVo.setPartLength(new BigDecimal(-1));
        partInfoResVo.setPartWidth(new BigDecimal(-1));
        partInfoResVo.setPartHeight(new BigDecimal(-1));
        partInfoResVo.setPartWeight(new BigDecimal(-1));
        partInfoResVo.setTotalCount(reqVo.getMatchcCount());
        partInfoResVo.setPalletCount(reqVo.getMatchcCount());
        partInfoResVo.setNextGroupNumber(this.mapToWorkPlace(reqVo.getMatchcNo()));
        partInfoResVo.setCode(0);
        partInfos.add(partInfoResVo);

        try {
            executor.execute(() -> {
                HttpHeaders header = new HttpHeaders();
                header.set("SOURCE", "APS");
                HttpEntity<Object> httpEntity = new HttpEntity<>(partInfos, header);
                logApiUtils.setReqStr(logApi, JsonUtils.toJsonString(partInfos));
                System.out.println(JsonUtils.toJsonString(httpEntity));
                String post = restTemplate.postForObject(URL, httpEntity, String.class);
                logApiUtils.saveDB(true, logApi, post, 2);
                log.info("WMS-托盘同步-结束：" + post);
            });
        } catch (Exception e) {
            logApiUtils.saveDB(false, logApi, e.getMessage(), 2);
            log.info("WMS-报工并装盘-结束-错误：" + e.getMessage());
        }
    }

    private String mapToWorkPlace(String matchcNo) {
        if (StringUtils.isNotBlank(matchcNo)) {
            if (matchcNo.contains("0101")) {
                return "3-2_ZHJT_0101";
            } else if ( matchcNo.contains("0201")) {
                return "3-2_ZHJT_0201";
            } else if ( matchcNo.contains("0301")) {
                return "3-2_ZHJT_0301";
            } else {
                return "xxx";
            }
        }else {
            return "xxx";
        }
    }
}
